import AMapLoader from "@amap/amap-jsapi-loader";

const SecurityJsCode = "32db2748cba717276c713ad0cc9cf21f";
const MapKey = "dcf4d205a84cf77955f91c0653d19bd9";

interface AMapInitConfigModel {
  elementId?: string;
  center?: [number, number];
  zoom?: number;
  zooms?: [number, number];
  plugins?: string[];
  mapStyle?: string;
}

interface AMapInitResult {
  map: any;
  AMap: any;
}

class AMapManager {
  private map: any;
  private AMap: any;
  private config: AMapInitConfigModel;

  /**
   * 构造函数用于初始化地图组件
   *
   * @param {AMapInitConfigModel} config - 地图初始化配置模型，包含地图组件的配置信息
   */
  constructor(config: AMapInitConfigModel) {
    this.config = config;
    this.map = null;
    this.AMap = null;
  }

  /**
   * 初始化地图服务
   * 此方法负责加载高德地图API并配置地图服务的相关参数
   * 它异步返回地图初始化的结果，包括地图实例和AMap库实例
   *
   * @returns {Promise<AMapInitResult>} 返回一个Promise，解析为包含地图初始化结果的对象
   */
  public async init(): Promise<AMapInitResult> {
    return new Promise((resolve, reject) => {
      window._AMapSecurityConfig = {
        securityJsCode: SecurityJsCode,
      };

      // 使用断言绕过类型检查
      (AMapLoader as any).reset();

      AMapLoader.load({
        key: MapKey,
        version: "2.0",
        plugins: this.config.plugins,
      })
        .then((AMapLib) => {
          this.AMap = AMapLib; // 将加载的 AMap 库赋值给全局变量

          this.map = new this.AMap.Map(this.config.elementId, {
            zoom: this.config.zoom,
            zooms: this.config.zooms,
            center: this.config.center,
            mapStyle: this.config.mapStyle,
          });

          /// 添加工具条控件
          if (this.config.plugins?.includes("AMap.ToolBar")) {
            this.map.addControl(
              new this.AMap.ToolBar({
                position: "LT",
              })
            );
          }

          /// 添加控件控件
          if (this.config.plugins?.includes("AMap.ControlBar")) {
            this.map.addControl(
              new this.AMap.ControlBar({
                position: "RT",
              })
            );
          }

          /// 添加定位控件
          if (this.config.plugins?.includes("AMap.Geolocation")) {
            this.map.addControl(
              new this.AMap.Geolocation({
                enableHighAccuracy: true,
              })
            );
          }

          resolve({
            map: this.map,
            AMap: this.AMap,
          });
        })
        .catch((e) => {
          console.log(e);
          reject(e);
        });
    });
  }

  /**
   * 查询行政区划数据
   * @param {string} name 行政区划名称
   */
  async getDistrictData(name: string) {
    return new Promise((resolve, reject) => {
      this.AMap.plugin(["AMap.DistrictSearch"], () => {
        const districtSearch = new this.AMap.DistrictSearch({
          subdistrict: 0,
          extensions: "all",
        });
        // 查询萍乡市的行政区划数据
        districtSearch.search(name, function (status: any, result: any) {
          if (status === "complete") {
            resolve(result.districtList[0]);
          } else {
            console.warn(status, result);
            reject("获取数据失败");
          }
        });
      });
    });
  }

  /**
   * 绘制多边形
   */
  drawPolygon(data: any) {
    if (!this.map) return;
    const polygon = new this.AMap.Polygon({
      strokeWeight: 1,
      path: data,
      fillOpacity: 0.4,
      fillColor: "#80d8ff",
      strokeColor: "#0091ea",
    });
    this.map.add(polygon);
    return polygon;
  }

  /**
   * 在地图上添加标记
   *
   * 此函数用于在地图上指定位置添加一个标记，并可以指定标记的标题、图标、标签内容以及自定义数据
   * 当用户点击标记时，会在控制台输出点击事件的详细信息和标记的自定义数据
   *
   * @param position 标记的位置，使用经纬度坐标表示
   * @param title 标记的标题，当鼠标悬停在标记上时显示
   * @param icon 标记的图标，指定标记在地图上的外观
   * @param labelContent 标记的标签内容，显示在标记旁边
   * @param extData 任意类型的自定义数据，可以是标记相关的额外信息
   */
  public addMarker(
    position: [number, number],
    title: string,
    icon: string,
    labelContent: string,
    extData: any
  ): any {
    if (!this.map) return;
    const marker = new this.AMap.Marker({
      map: this.map,
      position: position,
      title: title,
      icon: icon,
      label: {
        content: labelContent,
        direction: "bottom",
      },
      bubble: true,
      extData: extData, // 任何自定义属性
    });
    return marker;
  }

  /**
   * @description 海量点
   */
  public addLabelMarker(positions: any[], icon: string): any {
    if (!this.map) return;

    const labelsLayer = new this.AMap.LabelsLayer({
      zooms: [3, 20],
      zIndex: 1000,
      collision: true, //该层内标注是否避让
      allowCollision: true, //不同标注层之间是否避让
    });

    //设置一个图标对象
    const labelIcon = {
      type: "image", //图标类型，现阶段只支持 image 类型
      image: icon, //可访问的图片 URL
      size: [30, 30], //图片尺寸
      anchor: "center", //图片相对 position 的锚点，默认为 bottom-center
    };

    const labels = [];
    for (let i = 0; i < positions.length; i++) {
      const labelText = {
        content: positions[i].name,
      };

      //创建 LabelMarker
      const label = new this.AMap.LabelMarker({
        name: positions[i].name,
        position: positions[i].position,
        zIndex: 16,
        rank: 1, //避让优先级
        icon: labelIcon, //标注图标，将 icon 对象传给 icon 属性
        text: labelText,
        extData: positions[i].extData,
      });

      labels.push(label);
    }

    labelsLayer.add(labels);
    this.map.add(labelsLayer);
    return labels;
  }

  /**
   * @description 设置行政区域图层
   */
  public setDistrictLayer(): void {
    if (!this.map) return;

    //2、创建省市简易行政区图层
    var distProvince = new this.AMap.DistrictLayer.Province({
      zIndex: 10, //设置图层层级
      zooms: [2, 15], //设置图层显示范围
      adcode: "360300", //设置行政区 adcode
      depth: 2,
    });

    // 3、设置行政区图层样式
    distProvince.setStyles({
      "stroke-width": 2, //描边线宽
      "county-stroke": "#FFDAB9",
      fill: function (properties: any) {
        console.log(properties);
        return "#2d3748";
      },
    });

    //4、将简易行政区图层添加到地图
    this.map.add(distProvince);
  }

  public destroy(): void {
    if (this.map) {
      this.map.destroy();
    }
  }
}

export { AMapManager, AMapInitConfigModel, AMapInitResult };
